package com.cn.steam.iam.config;

import com.cn.steam.foundation.common.utils.CryptUtils;
import com.cn.steam.foundation.common.utils.Op;
import com.cn.steam.foundation.common.web.model.IamServerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;

import java.security.KeyPair;

/**
 * @author: zjm
 * @create: 2021-11-20 13:41
 **/
@Configuration
public class IamServerTokenConfiguration {
    @Autowired
    private IamServerConfig iamServerConfig;

    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;


    @Bean
    @ConfigurationProperties(prefix= "iam.server")
    public IamServerConfig createIamServerConfig() {
        return new IamServerConfig();
    }

    @Bean
    public TokenStore createTokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter);
    }

    /**
     * 什么是JWT
     * JSON Web Token（JWT）是一个开放标准（RFC 7519），它定义了一种紧凑且独立的方式，用于在各方之间作为JSON对象安全地传输信息。（更多信息建议去官网了解）
     *
     * 使用JWT替换传统Token有很多好处，比如：
     *
     * 简洁(Compact): 可以通过URL，POST参数或者在HTTP header发送，因为数据量小，传输速度也很快
     * 自包含(Self-contained)：负载中包含了所有用户所需要的信息，避免了多次查询数据库
     * 因为Token是以JSON加密的形式保存在客户端的，所以JWT是跨语言的，原则上任何web形式都支持。
     * 不需要在服务端保存会话信息，特别适用于分布式微服务。
     * 先了解一下使用到的两个组件的作用：
     * JwtAccessTokenConverter：TokenEnhancer的子类，帮助程序在JWT编码的令牌值和OAuth身份验证信息之间进行转换（在两个方向上），同时充当TokenEnhancer授予令牌的时间。
     * 自定义的JwtAccessTokenConverter（把自己设置的jwt签名加入accessTokenConverter中）
     * 原文链接：https://blog.csdn.net/qq_42654484/article/details/95216037
     * @return
     */
    @Bean
    public JwtAccessTokenConverter createJwtAccessTokenConverter(){
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        ClassPathResource resource = new ClassPathResource(iamServerConfig.getCertificateStoreFile());
        String key = iamServerConfig.getKey();
        String keyName = iamServerConfig.getKeyPair();
        if(Op.isNotEmpty(iamServerConfig.getSalt())){
            key = CryptUtils.aesDecrypt(iamServerConfig.getKey(),iamServerConfig.getSalt());
            keyName = CryptUtils.aesDecrypt(iamServerConfig.getKeyPair(),iamServerConfig.getSalt());
        }
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resource,key.toCharArray());
        KeyPair keyPair = keyStoreKeyFactory.getKeyPair(keyName);
        jwtAccessTokenConverter.setKeyPair(keyPair);
        return jwtAccessTokenConverter;
    }
}
